﻿#include "CameraManage.h"
#include <QGroupBox>
#include <QFormLayout>
#include "CameraHik.h"
#include "CameraIk.h"
#include <QApplication>
#include <QSettings>

#pragma execution_character_set("utf-8")

CameraManage::CameraManage(QObject *parent)
    : QObject{parent}
{
    //外部调用顺序
    //    setConfigWriteOneFunc();
    //    setConfigReadAllFunc();
    //    setConfigReadOneFunc();
    //    initCameraAll();
    //    initWgtCamStatus();
    //    initCameraManageWidget();
    //    startWorker();
    qRegisterMetaTypeStreamOperators<CameraConfig>("CameraConfig");

    configWriteOne = [](const CameraConfig& config){
        QSettings iniFile(QApplication::applicationDirPath() + "/Config.ini", QSettings::IniFormat);
        iniFile.setValue("CameraConfig/" + config.name, QVariant::fromValue(config));
    };
    configReadOne = [](QString name)->CameraConfig{
        QSettings iniFile(QApplication::applicationDirPath() + "/Config.ini", QSettings::IniFormat);
        CameraConfig config = iniFile.value("CameraConfig/" + name).value<CameraConfig>();
        return config;
    };
    configReadAll = []()->QMap<QString, CameraConfig>{
        QSettings iniFile(QApplication::applicationDirPath() + "/Config.ini", QSettings::IniFormat);
        iniFile.beginGroup("CameraConfig");
        QStringList keyList = iniFile.childKeys();
        QMap<QString, CameraConfig> mapConfig;
        for(auto key : keyList){
            CameraConfig config = iniFile.value(key).value<CameraConfig>();
            mapConfig.insert(config.name, config);
        }
        iniFile.endGroup();
        return mapConfig;
    };

    configRemoveOne = [](QString name){
        QSettings iniFile(QApplication::applicationDirPath() + "/Config.ini", QSettings::IniFormat);
        iniFile.remove("CameraConfig/" + name);
    };

}

void CameraManage::setConfigWriteOneFunc(void (*func)(const CameraConfig &))
{
    configWriteOne = func;
}

void CameraManage::setConfigReadAllFunc(QMap<QString, CameraConfig> (*func)())
{
    configReadAll = func;
}

void CameraManage::setConfigReadOneFunc(CameraConfig (*func)(QString))
{
    configReadOne = func;
}

void CameraManage::startWorker()
{
    for(auto thread : mMapCamThread.values()){
        thread->start();
    }
}

void CameraManage::checkCameraStatus()
{
    bool isStart = true;
    if(mMapCameraStart.size() != mMapCam.size()){
        isStart = false;
        goto checkEnd;
    }
    for(auto status : mMapCameraStart.values()){
        if(!status){
            isStart = false;
            break;
        }
    }
checkEnd:
    emit sigCameraStatus(isStart);
}

void CameraManage::onAddOne(const CameraConfig &config)
{
    if(mMapCam.contains(config.name))
        return;
    configWriteOne(config);
    initCameraOne(config);
    mMapCamThread.value(config.name)->start();
}

void CameraManage::onDeleteOne(const QString &name)
{
    if(!mMapCam.contains(name))
        return;
    CameraBase* cam = mMapCam.take(name);
    cam->quit();
    cam = nullptr;
    wgtCamStatus->removeOne(name);
    configRemoveOne(name);
}

void CameraManage::onConfigChanged(const CameraConfig &config)
{
    configWriteOne(config);
}

void CameraManage::initCameraAll()
{
    QMap<QString, CameraConfig> mapCamConfig = configReadAll();
    for(auto key : mapCamConfig.keys()){
        initCameraOne(mapCamConfig.value(key));
    }
}

void CameraManage::initCameraOne(CameraConfig config)
{
    CameraBase* camWorker;
    switch (config.brand) {
    case CB_HiK:
       camWorker = new CameraHik();
        break;
    case CB_Ik:
       camWorker = new CameraIk();
       break;
    default:
       camWorker = new CameraHik();
        break;
    }
    camWorker->setConfig(config);
    mMapCam.insert(config.name, camWorker);

    QThread* camThread = new QThread();
    mMapCamThread.insert(config.name, camThread);

    camWorker->moveToThread(camThread);
    connect(camThread, &QThread::started, camWorker, &CameraBase::onInit);
    connect(qApp, &QApplication::aboutToQuit, camWorker, &CameraBase::quit);
    connect(camWorker, &QObject::destroyed, camThread, &QThread::quit);
    connect(camThread, &QThread::finished, camThread, &QThread::deleteLater);
    connect(this, &CameraManage::sigSetCameraConfig, camWorker, &CameraBase::onConfigChanged);

    wgtCamStatus->addOne(config.name);

    //在相机管理页面添加一个
    mCameraManageWidget->addCamera(mMapCam.value(config.name));

    //连接相机的状态信号，并显示
    connect(camWorker, &CameraBase::sigStatusChanged, this, [&](const QString& camName, CameraStatus status){
        wgtCamStatus->setStatus(camName, CameraBase::mapStatusStr.value(status));
    });
    //相机掉线事件
    connect(camWorker, &CameraBase::sigErrorOccured, this, [&](const QString& camName, CameraErrorCode code){
        if(code == CEC_Remove){
            mMapCameraStart.insert(camName, false);
            checkCameraStatus();
        }
    });
    //相机打开成功信号
    connect(camWorker, &CameraBase::sigStartSucceed, this, [&, config](const QString& camName){
        emit sigSetCameraConfig(config);
        mMapCameraStart.insert(camName, true);
        checkCameraStatus();
    });
}

void CameraManage::initWgtCamStatus()
{
    wgtCamStatus = new CameraStatusWidget();
    wgtCamStatus->setMinimumWidth(200);
}

void CameraManage::initCameraManageWidget()
{
    mCameraManageWidget = new CameraManageWidget("相机调试");
    connect(mCameraManageWidget, &CameraManageWidget::sigAddOne, this, &CameraManage::onAddOne);
    connect(mCameraManageWidget, &CameraManageWidget::sigConfigChanged, this, &CameraManage::onConfigChanged);
    connect(mCameraManageWidget, &CameraManageWidget::sigDeleteOne, this, &CameraManage::onDeleteOne);
}
